home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / lib / python2.5 / mimify.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-29  |  12KB  |  515 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. '''Mimification and unmimification of mail messages.
  5.  
  6. Decode quoted-printable parts of a mail message or encode using
  7. quoted-printable.
  8.  
  9. Usage:
  10.         mimify(input, output)
  11.         unmimify(input, output, decode_base64 = 0)
  12. to encode and decode respectively.  Input and output may be the name
  13. of a file or an open file object.  Only a readline() method is used
  14. on the input file, only a write() method is used on the output file.
  15. When using file names, the input and output file names may be the
  16. same.
  17.  
  18. Interactive usage:
  19.         mimify.py -e [infile [outfile]]
  20.         mimify.py -d [infile [outfile]]
  21. to encode and decode respectively.  Infile defaults to standard
  22. input and outfile to standard output.
  23. '''
  24. MAXLEN = 200
  25. CHARSET = 'ISO-8859-1'
  26. QUOTE = '> '
  27. import re
  28. __all__ = [
  29.     'mimify',
  30.     'unmimify',
  31.     'mime_encode_header',
  32.     'mime_decode_header']
  33. qp = re.compile('^content-transfer-encoding:\\s*quoted-printable', re.I)
  34. base64_re = re.compile('^content-transfer-encoding:\\s*base64', re.I)
  35. mp = re.compile('^content-type:.*multipart/.*boundary="?([^;"\n]*)', re.I | re.S)
  36. chrset = re.compile('^(content-type:.*charset=")(us-ascii|iso-8859-[0-9]+)(".*)', re.I | re.S)
  37. he = re.compile('^-*\n')
  38. mime_code = re.compile('=([0-9a-f][0-9a-f])', re.I)
  39. mime_head = re.compile('=\\?iso-8859-1\\?q\\?([^? \t\n]+)\\?=', re.I)
  40. repl = re.compile('^subject:\\s+re: ', re.I)
  41.  
  42. class File:
  43.     '''A simple fake file object that knows about limited read-ahead and
  44.     boundaries.  The only supported method is readline().'''
  45.     
  46.     def __init__(self, file, boundary):
  47.         self.file = file
  48.         self.boundary = boundary
  49.         self.peek = None
  50.  
  51.     
  52.     def readline(self):
  53.         if self.peek is not None:
  54.             return ''
  55.         
  56.         line = self.file.readline()
  57.         if not line:
  58.             return line
  59.         
  60.         if self.boundary:
  61.             if line == self.boundary + '\n':
  62.                 self.peek = line
  63.                 return ''
  64.             
  65.             if line == self.boundary + '--\n':
  66.                 self.peek = line
  67.                 return ''
  68.             
  69.         
  70.         return line
  71.  
  72.  
  73.  
  74. class HeaderFile:
  75.     
  76.     def __init__(self, file):
  77.         self.file = file
  78.         self.peek = None
  79.  
  80.     
  81.     def readline(self):
  82.         if self.peek is not None:
  83.             line = self.peek
  84.             self.peek = None
  85.         else:
  86.             line = self.file.readline()
  87.         if not line:
  88.             return line
  89.         
  90.         if he.match(line):
  91.             return line
  92.         
  93.         while None:
  94.             self.peek = self.file.readline()
  95.             if (len(self.peek) == 0 or self.peek[0] != ' ') and self.peek[0] != '\t':
  96.                 return line
  97.             
  98.             line = line + self.peek
  99.             self.peek = None
  100.             continue
  101.             return None
  102.  
  103.  
  104.  
  105. def mime_decode(line):
  106.     '''Decode a single line of quoted-printable text to 8bit.'''
  107.     newline = ''
  108.     pos = 0
  109.     while None:
  110.         res = mime_code.search(line, pos)
  111.         if res is None:
  112.             break
  113.         
  114.         newline = newline + line[pos:res.start(0)] + chr(int(res.group(1), 16))
  115.         pos = res.end(0)
  116.         continue
  117.         return newline + line[pos:]
  118.  
  119.  
  120. def mime_decode_header(line):
  121.     '''Decode a header line to 8bit.'''
  122.     newline = ''
  123.     pos = 0
  124.     while None:
  125.         res = mime_head.search(line, pos)
  126.         if res is None:
  127.             break
  128.         
  129.         match = res.group(1)
  130.         match = ' '.join(match.split('_'))
  131.         newline = newline + line[pos:res.start(0)] + mime_decode(match)
  132.         pos = res.end(0)
  133.         continue
  134.         return newline + line[pos:]
  135.  
  136.  
  137. def unmimify_part(ifile, ofile, decode_base64 = 0):
  138.     '''Convert a quoted-printable part of a MIME mail message to 8bit.'''
  139.     multipart = None
  140.     quoted_printable = 0
  141.     is_base64 = 0
  142.     is_repl = 0
  143.     if ifile.boundary and ifile.boundary[:2] == QUOTE:
  144.         prefix = QUOTE
  145.     else:
  146.         prefix = ''
  147.     hfile = HeaderFile(ifile)
  148.     while None:
  149.         line = hfile.readline()
  150.         if not line:
  151.             return None
  152.         
  153.         if prefix and line[:len(prefix)] == prefix:
  154.             line = line[len(prefix):]
  155.             pref = prefix
  156.         else:
  157.             pref = ''
  158.         line = mime_decode_header(line)
  159.         if qp.match(line):
  160.             quoted_printable = 1
  161.             continue
  162.         
  163.         if decode_base64 and base64_re.match(line):
  164.             is_base64 = 1
  165.             continue
  166.         
  167.         if not prefix and repl.match(line):
  168.             is_repl = 1
  169.         
  170.         mp_res = mp.match(line)
  171.         if mp_res:
  172.             multipart = '--' + mp_res.group(1)
  173.         
  174.         if he.match(line):
  175.             break
  176.             continue
  177.         continue
  178.         if is_repl:
  179.             if quoted_printable or multipart:
  180.                 is_repl = 0
  181.             
  182.     while None:
  183.         line = ifile.readline()
  184.         if not line:
  185.             return None
  186.         
  187.         line = re.sub(mime_head, '\\1', line)
  188.         if prefix and line[:len(prefix)] == prefix:
  189.             line = line[len(prefix):]
  190.             pref = prefix
  191.         else:
  192.             pref = ''
  193.         while multipart:
  194.             if line == multipart + '--\n':
  195.                 ofile.write(pref + line)
  196.                 multipart = None
  197.                 line = None
  198.                 break
  199.             
  200.             if line == multipart + '\n':
  201.                 ofile.write(pref + line)
  202.                 nifile = File(ifile, multipart)
  203.                 unmimify_part(nifile, ofile, decode_base64)
  204.                 line = nifile.peek
  205.                 if not line:
  206.                     break
  207.                     continue
  208.                 continue
  209.             
  210.             break
  211.         if line and quoted_printable:
  212.             while line[-2:] == '=\n':
  213.                 line = line[:-2]
  214.                 newline = ifile.readline()
  215.                 if newline[:len(QUOTE)] == QUOTE:
  216.                     newline = newline[len(QUOTE):]
  217.                 
  218.                 line = line + newline
  219.             line = mime_decode(line)
  220.         
  221.         if line and is_base64 and not pref:
  222.             import base64 as base64
  223.             line = base64.decodestring(line)
  224.         
  225.         if line:
  226.             ofile.write(pref + line)
  227.             continue
  228.         continue
  229.         return None
  230.  
  231.  
  232. def unmimify(infile, outfile, decode_base64 = 0):
  233.     '''Convert quoted-printable parts of a MIME mail message to 8bit.'''
  234.     if type(infile) == type(''):
  235.         ifile = open(infile)
  236.         if type(outfile) == type('') and infile == outfile:
  237.             import os as os
  238.             (d, f) = os.path.split(infile)
  239.             os.rename(infile, os.path.join(d, ',' + f))
  240.         
  241.     else:
  242.         ifile = infile
  243.     if type(outfile) == type(''):
  244.         ofile = open(outfile, 'w')
  245.     else:
  246.         ofile = outfile
  247.     nifile = File(ifile, None)
  248.     unmimify_part(nifile, ofile, decode_base64)
  249.     ofile.flush()
  250.  
  251. mime_char = re.compile('[=\x7f-\xff]')
  252. mime_header_char = re.compile('[=?\x7f-\xff]')
  253.  
  254. def mime_encode(line, header):
  255.     '''Code a single line as quoted-printable.
  256.     If header is set, quote some extra characters.'''
  257.     if header:
  258.         reg = mime_header_char
  259.     else:
  260.         reg = mime_char
  261.     newline = ''
  262.     pos = 0
  263.     if len(line) >= 5 and line[:5] == 'From ':
  264.         newline = ('=%02x' % ord('F')).upper()
  265.         pos = 1
  266.     
  267.     while None:
  268.         res = reg.search(line, pos)
  269.         if res is None:
  270.             break
  271.         
  272.         newline = newline + line[pos:res.start(0)] + ('=%02x' % ord(res.group(0))).upper()
  273.         pos = res.end(0)
  274.         continue
  275.         line = newline + line[pos:]
  276.         newline = ''
  277.         while len(line) >= 75:
  278.             i = 73
  279.             while line[i] == '=' or line[i - 1] == '=':
  280.                 i = i - 1
  281.             i = i + 1
  282.             newline = newline + line[:i] + '=\n'
  283.             line = line[i:]
  284.         return newline + line
  285.  
  286. mime_header = re.compile('([ \t(]|^)([-a-zA-Z0-9_+]*[\x7f-\xff][-a-zA-Z0-9_+\x7f-\xff]*)(?=[ \t)]|\n)')
  287.  
  288. def mime_encode_header(line):
  289.     '''Code a single header line as quoted-printable.'''
  290.     newline = ''
  291.     pos = 0
  292.     while None:
  293.         res = mime_header.search(line, pos)
  294.         if res is None:
  295.             break
  296.         
  297.         newline = '%s%s%s=?%s?Q?%s?=' % (newline, line[pos:res.start(0)], res.group(1), CHARSET, mime_encode(res.group(2), 1))
  298.         pos = res.end(0)
  299.         continue
  300.         return newline + line[pos:]
  301.  
  302. mv = re.compile('^mime-version:', re.I)
  303. cte = re.compile('^content-transfer-encoding:', re.I)
  304. iso_char = re.compile('[\x7f-\xff]')
  305.  
  306. def mimify_part(ifile, ofile, is_mime):
  307.     '''Convert an 8bit part of a MIME mail message to quoted-printable.'''
  308.     has_cte = is_qp = is_base64 = 0
  309.     multipart = None
  310.     must_quote_body = must_quote_header = has_iso_chars = 0
  311.     header = []
  312.     header_end = ''
  313.     message = []
  314.     message_end = ''
  315.     hfile = HeaderFile(ifile)
  316.     while None:
  317.         line = hfile.readline()
  318.         if not line:
  319.             break
  320.         
  321.         if not must_quote_header and iso_char.search(line):
  322.             must_quote_header = 1
  323.         
  324.         if mv.match(line):
  325.             is_mime = 1
  326.         
  327.         if cte.match(line):
  328.             has_cte = 1
  329.             if qp.match(line):
  330.                 is_qp = 1
  331.             elif base64_re.match(line):
  332.                 is_base64 = 1
  333.             
  334.         
  335.         mp_res = mp.match(line)
  336.         if mp_res:
  337.             multipart = '--' + mp_res.group(1)
  338.         
  339.         if he.match(line):
  340.             header_end = line
  341.             break
  342.         
  343.         continue
  344.         while None:
  345.             line = ifile.readline()
  346.             if not line:
  347.                 break
  348.             
  349.             if multipart:
  350.                 if line == multipart + '--\n':
  351.                     message_end = line
  352.                     break
  353.                 
  354.                 if line == multipart + '\n':
  355.                     message_end = line
  356.                     break
  357.                 
  358.             
  359.             if is_base64:
  360.                 message.append(line)
  361.                 continue
  362.             
  363.             if is_qp:
  364.                 while line[-2:] == '=\n':
  365.                     line = line[:-2]
  366.                     newline = ifile.readline()
  367.                     if newline[:len(QUOTE)] == QUOTE:
  368.                         newline = newline[len(QUOTE):]
  369.                     
  370.                     line = line + newline
  371.                 line = mime_decode(line)
  372.             
  373.             if not has_iso_chars:
  374.                 if iso_char.search(line):
  375.                     has_iso_chars = must_quote_body = 1
  376.                 
  377.             
  378.             if not must_quote_body:
  379.                 if len(line) > MAXLEN:
  380.                     must_quote_body = 1
  381.                 
  382.             len(line) > MAXLEN
  383.             continue
  384.             for line in header:
  385.                 if must_quote_header:
  386.                     line = mime_encode_header(line)
  387.                 
  388.                 chrset_res = chrset.match(line)
  389.                 if chrset_res:
  390.                     if has_iso_chars:
  391.                         if chrset_res.group(2).lower() == 'us-ascii':
  392.                             line = '%s%s%s' % (chrset_res.group(1), CHARSET, chrset_res.group(3))
  393.                         
  394.                     else:
  395.                         line = '%sus-ascii%s' % chrset_res.group(1, 3)
  396.                 
  397.                 if has_cte and cte.match(line):
  398.                     line = 'Content-Transfer-Encoding: '
  399.                     if is_base64:
  400.                         line = line + 'base64\n'
  401.                     elif must_quote_body:
  402.                         line = line + 'quoted-printable\n'
  403.                     else:
  404.                         line = line + '7bit\n'
  405.                 
  406.                 ofile.write(line)
  407.             
  408.     if (must_quote_header or must_quote_body) and not is_mime:
  409.         ofile.write('Mime-Version: 1.0\n')
  410.         ofile.write('Content-Type: text/plain; ')
  411.         if has_iso_chars:
  412.             ofile.write('charset="%s"\n' % CHARSET)
  413.         else:
  414.             ofile.write('charset="us-ascii"\n')
  415.     
  416.     if must_quote_body and not has_cte:
  417.         ofile.write('Content-Transfer-Encoding: quoted-printable\n')
  418.     
  419.     ofile.write(header_end)
  420.     for line in message:
  421.         if must_quote_body:
  422.             line = mime_encode(line, 0)
  423.         
  424.         ofile.write(line)
  425.     
  426.     ofile.write(message_end)
  427.     line = message_end
  428.     while multipart:
  429.         if line == multipart + '--\n':
  430.             while None:
  431.                 line = ifile.readline()
  432.                 if not line:
  433.                     return None
  434.                 
  435.                 if must_quote_body:
  436.                     line = mime_encode(line, 0)
  437.                 
  438.                 continue
  439.         line == multipart + '--\n'
  440.         if line == multipart + '\n':
  441.             nifile = File(ifile, multipart)
  442.             mimify_part(nifile, ofile, 1)
  443.             line = nifile.peek
  444.             if not line:
  445.                 break
  446.             
  447.             ofile.write(line)
  448.             continue
  449.         
  450.         while None:
  451.             line = ifile.readline()
  452.             if not line:
  453.                 return None
  454.             
  455.             if must_quote_body:
  456.                 line = mime_encode(line, 0)
  457.             
  458.             continue
  459.         return None
  460.  
  461.  
  462. def mimify(infile, outfile):
  463.     '''Convert 8bit parts of a MIME mail message to quoted-printable.'''
  464.     if type(infile) == type(''):
  465.         ifile = open(infile)
  466.         if type(outfile) == type('') and infile == outfile:
  467.             import os
  468.             (d, f) = os.path.split(infile)
  469.             os.rename(infile, os.path.join(d, ',' + f))
  470.         
  471.     else:
  472.         ifile = infile
  473.     if type(outfile) == type(''):
  474.         ofile = open(outfile, 'w')
  475.     else:
  476.         ofile = outfile
  477.     nifile = File(ifile, None)
  478.     mimify_part(nifile, ofile, 0)
  479.     ofile.flush()
  480.  
  481. import sys
  482. if (__name__ == '__main__' or len(sys.argv) > 0) and sys.argv[0] == 'mimify':
  483.     import getopt
  484.     usage = 'Usage: mimify [-l len] -[ed] [infile [outfile]]'
  485.     decode_base64 = 0
  486.     (opts, args) = getopt.getopt(sys.argv[1:], 'l:edb')
  487.     if len(args) not in (0, 1, 2):
  488.         print usage
  489.         sys.exit(1)
  490.     
  491.     if ((('-e', '') in opts) == (('-d', '') in opts) or ('-b', '') in opts) and ('-d', '') not in opts:
  492.         print usage
  493.         sys.exit(1)
  494.     
  495.     for o, a in opts:
  496.         if o == '-e':
  497.             encode = mimify
  498.             continue
  499.         None if o == '-d' else None<EXCEPTION MATCH>(ValueError, OverflowError)
  500.         if o == '-b':
  501.             decode_base64 = 1
  502.             continue
  503.     
  504.     if len(args) == 0:
  505.         encode_args = (sys.stdin, sys.stdout)
  506.     elif len(args) == 1:
  507.         encode_args = (args[0], sys.stdout)
  508.     else:
  509.         encode_args = (args[0], args[1])
  510.     if decode_base64:
  511.         encode_args = encode_args + (decode_base64,)
  512.     
  513.     encode(*encode_args)
  514.  
  515.